<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>Android——Tensorflow-Lite简单使用 | 海晨忆的博客</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  
  
  
  <meta name="description" content="&amp;emsp;&amp;emsp;项目里面用到了tflite，用于做简单的图片处理，不是判断图片是什么类型，就是传进去图片，生成新图片，类似于前面一篇讲的GPUImage的滤镜功能，但是比滤镜功能更加强大。">
<meta property="og:type" content="article">
<meta property="og:title" content="Android——Tensorflow-Lite简单使用">
<meta property="og:url" content="https://haichenyi.com/2019/06/11/Android——Tensorflow-Lite简单使用/index.html">
<meta property="og:site_name" content="海晨忆的博客">
<meta property="og:description" content="&amp;emsp;&amp;emsp;项目里面用到了tflite，用于做简单的图片处理，不是判断图片是什么类型，就是传进去图片，生成新图片，类似于前面一篇讲的GPUImage的滤镜功能，但是比滤镜功能更加强大。">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2019-06-11T14:40:00.369Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Android——Tensorflow-Lite简单使用">
<meta name="twitter:description" content="&amp;emsp;&amp;emsp;项目里面用到了tflite，用于做简单的图片处理，不是判断图片是什么类型，就是传进去图片，生成新图片，类似于前面一篇讲的GPUImage的滤镜功能，但是比滤镜功能更加强大。">
  
    <link rel="alternate" href="/atom.xml" title="海晨忆的博客" type="application/atom+xml">
  
  
    <link rel="icon" href="/uploads/artistic_image/head.jpg">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  <link rel="stylesheet" href="/css/style.css">
  <link rel="stylesheet" href="/css/highlight.css">
  <script>
  let antiquityStorage = window.sessionStorage.getItem('antiquitySessionStorage');
  if (antiquityStorage == '' || antiquityStorage == null) {
    var antiquityLoader = '<div id="loaderbox"><div class="loader"><div class="load-roll"><div class="load-top"></div><div class="load-right"></div><div class="load-bottom"></div></div></div></div>';
    document.write(antiquityLoader);
    document.body.style.overflow = 'hidden'
  }
  </script>
</head>

<body>
  <div id="fullpage" class="mobile-nav-right">
    
      <div id="wrapper" style="background-image: url(/uploads/artistic_image/bg.jpg)" title="背景图片来自网络">
    
    
      <header id="header">
  <div id="nav-toggle" class="nav-toggle"></div>
  <div class="head-box global-width">
    <nav class="nav-box nav-right">
      
        <a class="nav-item" href="/" title
        
        >首页</a>
      
        <a class="nav-item" href="/archives" title
        
        >归档</a>
      
        <a class="nav-item" href="/about" title
        
        >简历</a>
      
    </nav>
  </div>
</header>
      <div id="middlecontent" title class="global-width sidebar-left">
        <section id="main"><article id="post-Android——Tensorflow-Lite简单使用" class="article global-container article-type-post" itemscope itemprop="blogPost">
  
    <header class="article-header">
      
  
    <h1 class="article-title" itemprop="name">
      Android——Tensorflow-Lite简单使用
    </h1>
  

    </header>
  
  <div class="article-meta">
    <a href="/2019/06/11/Android——Tensorflow-Lite简单使用/" class="article-date">
  <time datetime="2019-06-11T14:33:16.000Z" itemprop="datePublished">2019-06-11</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/Android-常用功能/">Android -常用功能</a>
  </div>

    
  </div>
  
    <span id="busuanzi_container_page_pv">
      本文总阅读量<span id="busuanzi_value_page_pv"></span>次
    </span>
  

  <div class="article-inner">
    
    <div class="article-content article-content-cloud doorframe mac" itemprop="articleBody">
      
        <p>&emsp;&emsp;项目里面用到了tflite，用于做简单的图片处理，不是判断图片是什么类型，就是传进去图片，生成新图片，类似于前面一篇讲的GPUImage的滤镜功能，但是比滤镜功能更加强大。</p>
<a id="more"></a>
<p>&emsp;&emsp;我这里要做的就是集成，拿人家训练好的模型直接来用，我不用去训练模型。</p>
<h3 id="第一步-依赖"><a href="#第一步-依赖" class="headerlink" title="第一步 依赖"></a>第一步 依赖</h3><div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">//依赖库</span><br><span class="line">implementation &apos;org.tensorflow:tensorflow-lite:0.0.0-nightly&apos;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">android &#123;</span><br><span class="line">    ···</span><br><span class="line">    //set no compress models</span><br><span class="line">    aaptOptions &#123;</span><br><span class="line">        noCompress &quot;tflite&quot;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
<h3 id="第二步-加载训练模型"><a href="#第二步-加载训练模型" class="headerlink" title="第二步 加载训练模型"></a>第二步 加载训练模型</h3><p>&emsp;&emsp;网上很多介绍资料都是把训练模型直接copy到项目main目录下的assets目录（不存在就创建）与java目录平级，自然，这样的加载方式就是</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">// load infer model</span><br><span class="line">    private void loadModel(String model) &#123;</span><br><span class="line">        try &#123;</span><br><span class="line">            tflite = new Interpreter(loadModelFile(model));</span><br><span class="line">            Log.d(TAG, model + &quot; model load success&quot;);</span><br><span class="line">            tflite.setNumThreads(4);</span><br><span class="line">            load_result = true;</span><br><span class="line">        &#125; catch (IOException e) &#123;</span><br><span class="line">            Log.d(TAG, model + &quot; model load fail&quot;);</span><br><span class="line">            load_result = false;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    /**</span><br><span class="line">     * Memory-map the model file in Assets.</span><br><span class="line">     */</span><br><span class="line">    private MappedByteBuffer loadModelFile(String model) throws IOException &#123;</span><br><span class="line">        AssetFileDescriptor fileDescriptor = getApplicationContext().getAssets().openFd(model + &quot;.tflite&quot;);</span><br><span class="line">        FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());</span><br><span class="line">        FileChannel fileChannel = inputStream.getChannel();</span><br><span class="line">        long startOffset = fileDescriptor.getStartOffset();</span><br><span class="line">        long declaredLength = fileDescriptor.getDeclaredLength();</span><br><span class="line">        return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;一个tflite文件就好几M，甚至十几M，全部copy到项目里面不显示，所以，我们一般项目里面用都是先下载，然后再使用，那，这样的方式，我们要怎么加载训练模型呢？</p>
<p>&emsp;&emsp;我们先分析一下再assets目录下面怎么加载的？说白了就是新建一个Interpreter对象，就是加载模型。上面的方法都过时了，我们可以找到Interpreter类，里面你会看到如下的方法</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">//第一个参数传tflite文件，第二个参数传一个Interpreter静态内部类对象</span><br><span class="line">public Interpreter(@NonNull File modelFile, Interpreter.Options options) &#123;</span><br><span class="line">        this.wrapper = new NativeInterpreterWrapper(modelFile.getAbsolutePath(), options);</span><br><span class="line">&#125;</span><br><span class="line">    </span><br><span class="line">//所以，我们自己项目里面加载模型，用如下方式即可</span><br><span class="line">Interpreter.Options options = new Interpreter.Options();</span><br><span class="line">options.setNumThreads(4);</span><br><span class="line">tflite = new Interpreter(new File(&quot;&quot;), options);</span><br></pre></td></tr></table></figure></div>
<h3 id="第三步-执行run方法"><a href="#第三步-执行run方法" class="headerlink" title="第三步 执行run方法"></a>第三步 执行run方法</h3><div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tflite.run(in, out);</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;通过执行这个run方法，获取我们需要的东西，第一个参数，输入对象，第二个参数，输出参数。</p>
<p><strong><em>重点，敲黑板</em></strong></p>
<p><strong><em>重点，敲黑板</em></strong></p>
<p><strong><em>重点，敲黑板</em></strong></p>
<p>&emsp;&emsp;重点就在这里，这里的输入和输出参数要怎么传？我这里训练模型是用Python做的，它需要传入一个四维数组，所以，输出我们自然也要用一个四维数组接收。</p>
<p>&emsp;&emsp;这里的四维数组怎么传递呐？就要说到Android里面的bitmap知识了，它的每个像素点都是一个ARGB数组。即透明度，红色，绿色，蓝色。我们前面的灰色滤镜之类的东西，实际上就是改变RGB三原色的值，让颜色变成灰色，然后改变亮度之类的就是改变每个管道的透明度。网上有很多这样的知识。</p>
<p>&emsp;&emsp;再来说说这个四维数组，我项目里面用到的这个四维数组：<strong><em>1 X 256 X 256 X 3</em></strong>，这几个值怎么理解呢？</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">1：表示一张图片</span><br><span class="line"></span><br><span class="line">256X256：表示图片的宽高</span><br><span class="line"></span><br><span class="line">3：表示RGB色值</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;那我们怎么把bitmap对象，转换成我们需要的四维数组呐？</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">//定义了一个一维数组，里面就是我们需要的参数，便于修改</span><br><span class="line">private int[] ddims = &#123;1, 256, 256, 3&#125;;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 获取图片的四维数组</span><br><span class="line">     * @param bitmap bitmap对象</span><br><span class="line">     * @param ddims 参数数组</span><br><span class="line">     * @return 图片四维数组</span><br><span class="line">     */</span><br><span class="line">public float[][][][] getScaledMatrix(Bitmap bitmap, int[] ddims) &#123;</span><br><span class="line">        //新建一个1*256*256*3的四维数组</span><br><span class="line">        float[][][][] inFloat = new float[ddims[0]][ddims[1]][ddims[2]][ddims[3]];</span><br><span class="line">        //新建一个一维数组，长度是图片像素点的数量</span><br><span class="line">        int[] pixels = new int[ddims[1] * ddims[2]];</span><br><span class="line">        //把原图缩放成我们需要的图片大小</span><br><span class="line">        Bitmap bm = Bitmap.createScaledBitmap(bitmap, ddims[1], ddims[2], false);</span><br><span class="line">        //把图片的每个像素点的值放到我们前面新建的一维数组中</span><br><span class="line">        bm.getPixels(pixels, 0, bm.getWidth(), 0, 0, ddims[1], ddims[2]);</span><br><span class="line">        int pixel = 0;</span><br><span class="line">        //for循环，把每个像素点的值转换成RBG的值，存放到我们的目标数组中</span><br><span class="line">        for (int i = 0; i &lt; ddims[1]; ++i) &#123;</span><br><span class="line">            for (int j = 0; j &lt; ddims[2]; ++j) &#123;</span><br><span class="line">                final int val = pixels[pixel++];</span><br><span class="line">                float red = ((val &gt;&gt; 16) &amp; 0xFF);</span><br><span class="line">                float green = ((val &gt;&gt; 8) &amp; 0xFF);</span><br><span class="line">                float blue = (val &amp; 0xFF);</span><br><span class="line">                float[] arr = &#123;red, green, blue&#125;;</span><br><span class="line">                inFloat[0][i][j] = arr;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        if (bm.isRecycled()) &#123;</span><br><span class="line">            bm.recycle();</span><br><span class="line">        &#125;</span><br><span class="line">        return inFloat;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;上面代码注释写的很清楚了吧？每一行都有注释，for循环的作用也标的很清楚，通过这个方法，我们得到的就是我们想要的四维数组了，这里的四维数组的格式，图片的大小，都是tflite文件建模型的时候设置好的，看你们训练模型的工程师是怎么定义的，你就怎么传。</p>
<p>&emsp;&emsp;然后，新建一个一模一样格式的数组去接收输出值，也是一个四维数组，那么，我们怎么把这个四维数组转换成我们需要的bitmap呢？</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">//创建bitmap的方法，</span><br><span class="line">Bitmap.createBitmap(@NonNull @ColorInt int[] colors,</span><br><span class="line">            int width, int height, Config config);</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;就是这个方法，传一个一维颜色数组，图片的宽高，还有一个图片的格式，那我们这里就是要把这个四维数组转成一个一维的颜色数组了。</p>
<div class="highlight-box"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 四维数组转成bitmap对象</span><br><span class="line"> * @param outArr 数组</span><br><span class="line"> * @param ddims 格式</span><br><span class="line"> * @return bitmap</span><br><span class="line"> */</span><br><span class="line">public Bitmap getBitmap(float[][][][] outArr, int[] ddims) &#123;</span><br><span class="line">    //获取图片的三维数组</span><br><span class="line">    float[][][] temp = outArr[0];</span><br><span class="line">    int n = 0;</span><br><span class="line">    //新建一个接收的颜色数组，长度就是图片的宽高之积，类似于上面的像素那个数组</span><br><span class="line">    int[] colorArr = new int[ddims[1] * ddims[2]];</span><br><span class="line">    //for循环遍历把图片的ARGB色值转成一个颜色值，放入颜色数组中</span><br><span class="line">    for (int i = 0; i &lt; ddims[1]; i++) &#123;</span><br><span class="line">        for (int j = 0; j &lt; ddims[2]; j++) &#123;</span><br><span class="line">            float[] arr = temp[i][j];</span><br><span class="line">            int alpha = 255;</span><br><span class="line">            int red = (int) arr[0];</span><br><span class="line">            int green = (int) arr[1];</span><br><span class="line">            int blue = (int) arr[2];</span><br><span class="line">            int tempARGB = (alpha &lt;&lt; 24) | (red &lt;&lt; 16) | (green &lt;&lt; 8) | blue;</span><br><span class="line">            colorArr[n++] = tempARGB;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    //创建bitmap对象</span><br><span class="line">    return Bitmap.createBitmap(colorArr, ddims[1], ddims[2], Bitmap.Config.ARGB_8888);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div>
<p>&emsp;&emsp;至此，我们就拿到了，我们需要的bitmap对象了，然后再做后续的逻辑即可。</p>
<p><a href="https://download.csdn.net/download/qq_27634797/11199751" target="_blank" rel="noopener">项目链接</a></p>

      
    </div>
    
      <footer class="article-footer">
        完
      </footer>
    
  </div>
  
    
<nav id="article-nav">
  <div class="article-nav-block">
    
      <a href="/2019/06/11/kotlin之基础/" id="article-nav-newer" class="article-nav-link-wrap">
        <strong class="article-nav-caption"></strong>
        <div class="article-nav-title">
          
            kotlin之基础
          
        </div>
      </a>
    
  </div>
  <div class="article-nav-block">
    
      <a href="/2019/06/11/图片滤镜——GPUImage/" id="article-nav-older" class="article-nav-link-wrap">
        <div class="article-nav-title">图片滤镜——GPUImage</div>
        <strong class="article-nav-caption"></strong>
      </a>
    
  </div>
</nav>

    
  
  
</article>
</section>
        <aside id="sidebar">
  
    <div class="widget-box">
  <div class="avatar-box avatar-item">
    <img class="avatar" src="/uploads/artistic_image/head.jpg" title="头像来自网络"></img>
    <h3 class="avatar-name">
      
        海晨忆
      
    </h3>
    <p class="avatar-slogan">
      先谋生，再谋爱。人间值得，未来可期。
    </p>
  </div>
</div>


  
    
  <div class="widget-box">
    <h3 class="widget-title">分类</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Android-Socket/">Android -Socket</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-加密算法/">Android -加密算法</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-常用功能/">Android -常用功能</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-框架/">Android -框架</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-源码解析/">Android -源码解析</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-自定义view/">Android -自定义view</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-设计模式/">Android -设计模式</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/JAVA-并发/">JAVA -并发</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Java-SpringBoot/">Java -SpringBoot</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Tomcat/">Tomcat</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/kotlin/">kotlin</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/数据库-JDBC/">数据库 -JDBC</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/数据库-MySQL/">数据库 -MySQL</a></li></ul>
    </div>
  </div>


  
    

  
    
  
    
  <div class="widget-box">
    <h3 class="widget-title">归档</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/07/">July 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/11/">November 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/10/">October 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/09/">September 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/08/">August 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/07/">July 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/06/">June 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/10/">October 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/05/">May 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/03/">March 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/02/">February 2018</a></li></ul>
    </div>
  </div>

  
    
  <div class="widget-box">
    <h3 class="widget-title">最新文章</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2021/07/27/JAVA—公平锁，非公平锁，悲观锁，乐观锁，死锁/">JAVA—公平锁，非公平锁，悲观锁，乐观锁，死锁</a>
          </li>
        
          <li>
            <a href="/2021/07/19/JAVA—线程同步器AQS/">JAVA—线程同步器AQS</a>
          </li>
        
          <li>
            <a href="/2021/07/07/Android模拟点击/">Android模拟点击</a>
          </li>
        
          <li>
            <a href="/2019/11/27/SpringBoot系列-消息-RabbitMQ-（二十）/">SpringBoot系列-消息(RabbitMQ)（二十）</a>
          </li>
        
          <li>
            <a href="/2019/11/13/SpringBoot系列-Docker（十九）/">SpringBoot系列-Docker（十九）</a>
          </li>
        
      </ul>
    </div>
  </div>

  
      <div class="widget-box">
    <h3 class="widget-title">友情链接</h3>
    <div class="widget">
      
        <a class="hrf" style="display: block;" href="https://github.com/haichenyi" title target='_blank'
        >Github</a>
      
        <a class="hrf" style="display: block;" href="https://www.jianshu.com/u/6077ee440c37" title target='_blank'
        >简书</a>
      
        <a class="hrf" style="display: block;" href="https://blog.csdn.net/qq_27634797" title target='_blank'
        >CSDN</a>
      
    </div>
  </div>

  
</aside>
      </div>
      <footer id="footer">
  <div class="foot-box footers global-width">
    &copy;2017-2021 海晨忆 &nbsp;&nbsp;
    <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span id="busuanzi_container_site_pv">阁下是第<span id="busuanzi_value_site_pv"></span>个访客</span>
  </div>
</footer>
      <script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<script>
if (!window.jQuery) {
var script = document.createElement('script');
script.src = "/js/jquery-2.0.3.min.js";
document.body.write(script);
}
</script>

  <link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
  <script src="/fancybox/jquery.fancybox.pack.js"></script>


<script src="/js/script.js"></script>



    </div>
    <nav id="mobile-nav" class="mobile-nav-box">
  <div class="mobile-nav-img mobile-nav-top"></div>
  
    <a href="/" class="mobile-nav-link">首页</a>
  
    <a href="/archives" class="mobile-nav-link">归档</a>
  
    <a href="/about" class="mobile-nav-link">简历</a>
  
  <div class="mobile-nav-img  mobile-nav-bottom"></div>
</nav>    
  </div>
</body>
</html>